package com.example.huajia.wx.controller;

import cn.hutool.core.util.RandomUtil;
import com.example.huajia.wx.common.util.R;
import com.example.huajia.wx.common.util.SnowFlakeGenerateIdWorker;
import com.example.huajia.wx.config.shiro.JwtUtil;
import com.example.huajia.wx.controller.form.*;
import com.example.huajia.wx.db.dao.ChatmsgDao;
import com.example.huajia.wx.db.dao.TbActivityDao;
import com.example.huajia.wx.exception.HJException;
import com.example.huajia.wx.service.ActivityService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.huajia.wx.common.util.RedisKey.*;

@RestController
@RequestMapping("/activity")
@Api("活动模块接口")
public class ActivityController {
    @Resource
    private ActivityService activityService;
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private TbActivityDao activityDao;
    @Resource
    private ChatmsgDao chatmsgDao;

    @PostMapping("/searchAllActivityByPage")
    @ApiOperation("分页查询活动接口")
    public R searchAllActivityByPage(@Valid @RequestBody SearchAllActivityByPageForm form, @RequestHeader("token") String token) {
        //1.通过token获得UserId
        int userId = jwtUtil.getUserId(token);
        //2.将分页的参数page和length取出来
        Integer page = form.getPage();
        Integer length = form.getLength();
        String searchKey = form.getKey();

        //3.开始计算分页的开始位置
        long start = (page - 1) * length;
        long end = start + length - 1;
        //4.分别将userId、start、length放入HashMap中
        HashMap map = new HashMap();
        map.put("userId", userId);
        map.put("start", start);
        map.put("length", length);
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String now = currentDate.format(formatter);
        map.put("now", now);
        if (searchKey != null) {
            map.put("key", searchKey);
            ArrayList<HashMap> list = activityService.searchActivityByKeyByPage(map);
            return R.ok().put("result", list);
        }
        //先判断redis里面是否存在缓存数据
        String key = ACTIVITY_ALL_KEY;
        List range = redisTemplate.opsForList().range(key, start, end);
        //判断redis是否有数据
        if (range.isEmpty()) {
            //如果为空，则需调用数据库查询
            ArrayList<HashMap> list = activityService.searchAllActivityByPage(map);
            return R.ok().put("result", list);
        }
        //如果不为空，直接从redis取出数据返回给后端
        return R.ok().put("result", range);
    }

    @PostMapping("/searchMyPublishByPage")
    @ApiOperation("分页查询我发布的活动接口")
    public R searchMyPublishByPage(@Valid @RequestBody SearchMyPublishByPageForm form, @RequestHeader("token") String token) {
        //1.通过token获得UserId
        int userId = jwtUtil.getUserId(token);
        //2.将分页的参数page和length取出来
        Integer page = form.getPage();
        Integer length = form.getLength();
        //3.开始计算分页的开始位置
        long start = (page - 1) * length;
        long end = start + length - 1;
        //4.分别将userId、start、length放入HashMap中
        HashMap map = new HashMap();
        map.put("publisherId", userId);
        map.put("start", start);
        map.put("length", length);
        //先判断redis里面是否存在缓存数据
        String key = ACTIVITY_MY_ACTIVITY_KEY + userId;
        List range = redisTemplate.opsForList().range(key, start, end);
        //判断redis是否有数据
        if (range.isEmpty()) {
            //如果为空，则需调用数据库查询
            ArrayList<HashMap> list = activityService.searchMyPublishByPage(map);
            return R.ok().put("result", list);
        }
        //如果不为空，直接从redis取出数据返回给后端
        return R.ok().put("result", range);
    }

    @PostMapping("/searchMyParticipationByPage")
    @ApiOperation("分页查询我参与的活动接口")
    public R searchMyParticipationByPage(@Valid @RequestBody SearchMyParticipationByPageForm form, @RequestHeader("token") String token) {
        //1.通过token获得UserId
        Integer userId = jwtUtil.getUserId(token);
        //2.将分页的参数page和length取出来
        Integer page = form.getPage();
        Integer length = form.getLength();
        //3.开始计算分页的开始位置
        long start = (page - 1) * length;
        long end = start + length - 1;
        //4.分别将userId、start、length放入HashMap中
        HashMap map = new HashMap();
        map.put("userId", userId);
        map.put("enrollmentUser", userId.toString());
        map.put("start", start);
        map.put("length", length);
        //先判断redis里面是否存在缓存数据
        String key = ACTIVITY_MY_PAR_KEY + userId;
        List range = redisTemplate.opsForList().range(key, start, end);
        //判断redis是否有数据
        if (range.isEmpty()) {
            //如果为空，则需调用数据库查询
            ArrayList<HashMap> list = activityService.searchMyParticipationByPage(map);
            return R.ok().put("result", list);
        }
        //如果不为空，直接从redis取出数据返回给后端
        return R.ok().put("result", range);
    }

    @PostMapping("/searchActivityContentById")
    @ApiOperation("查询活动详情接口")
    public R searchActivityContentById(@RequestBody SearchActivityContentByIdForm form, @RequestHeader("token") String token) {
        //取出id
        String id = form.getId();
        String key = ACTIVITY_CONTENT_KEY + id;
        //判断redis里面是否有数据
        List range = redisTemplate.opsForList().range(key, 0, 0);
        //判断是否为空
        if (range.isEmpty()) {
            //如果为空，需要去数据库查询
            ArrayList<HashMap> list = activityService.searchActivityContentById(id);
            return R.ok().put("result", list);
        }
        //如果不为空，直接返回redis里面的数据
        return R.ok().put("result", range.get(0));
    }

    @PostMapping("/insertActivity")
    @ApiOperation("发布活动接口")
    public R insertActivity(@RequestBody InsertActivityForm form, @RequestHeader("token") String token) {
        //拿到发布者id
        int userId = jwtUtil.getUserId(token);
        String firstPlace = form.getProvince() + form.getCity() + form.getDistrict();
        String detailedPlace = form.getDetailedPlace();
        String place = firstPlace + detailedPlace;
        String number = RandomUtil.randomNumbers(6);
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker = new SnowFlakeGenerateIdWorker(0L, 0L);
        String id = snowFlakeGenerateIdWorker.generateNextId();
        HashMap map = new HashMap();
        map.put("id", id);
        map.put("title", form.getTitle());
        map.put("content", form.getContent());
        map.put("publisherId", userId);
        map.put("place", place);
        map.put("tel", form.getTel());
        map.put("beginTime", form.getBeginTime());
        map.put("endTime", form.getEndTime());
        map.put("durationHour", form.getDurationHour());
        map.put("durationMin", form.getDurationMin());
        map.put("ord", form.getOrd());
        map.put("applicantNum", form.getApplicantNum());
        map.put("number", number);
        map.put("district", form.getDistrict());
        map.put("lea", form.getApplicantNum());
        map.put("endEnrollTime", form.getEndEnrollTime());
        Integer row = activityService.insertActivity(map);
        if (row == null) {
            throw new HJException("活动发布失败，请重试!");
        }
        return R.ok().put("result", "活动发布成功！");
    }


    @PostMapping("/updateActivityEnrollment")
    @ApiOperation("更新剩余名额接口")
    public R updateActivityEnrollment(@RequestBody UpdateActivityEnrollmentForm form, @RequestHeader("token") String token) {
        //拿到发布者id
        int userId = jwtUtil.getUserId(token);
        //获取活动id
        String id = form.getId();
        ArrayList enrollmentUser = new ArrayList();
        enrollmentUser.add(userId);
        HashMap map = new HashMap();
        map.put("id", id);
        map.put("enrollmentUser", enrollmentUser.toString());
        map.put("userId", userId);
        String key = ACTIVITY_MY_PAR_KEY + userId;
        //更新前需要判断是不是自己发布的活动
        int count = activityDao.isMineParticipation(map);
        if (count > 0) {
            throw new HJException("不能报名自己发布的活动！");
        }
        Integer row = activityService.updateActivityEnrollment(map);
        if (row == -1) {
            throw new HJException("你已报名，请勿重复报名！");
        }
        if (row == 0) {
            throw new HJException("报名失败！");
        }
        redisTemplate.expire(key, 1L, TimeUnit.SECONDS);
        return R.ok().put("result", "报名成功！");
    }

    @PostMapping("/isFinished")
    @ApiOperation("查询我发布的或参与的已结束活动")
    public R isFinished(@RequestBody @Valid IsFinishedForm form, @RequestHeader("token") String token){
        Integer userId = jwtUtil.getUserId(token);
        Integer length = form.getLength();
        Integer page = form.getPage();
        //开始计算分页的开始位置
        long start = (page - 1) * length;
        long end = start + length - 1;
        HashMap map = new HashMap();
        map.put("userId", userId.toString());
        map.put("start", start);
        map.put("length", length);
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String now = currentDate.format(formatter);
        map.put("now", now);
        ArrayList<HashMap> list = activityDao.isFinished(map);
        return R.ok().put("result", list);
    }

    @PostMapping("/checkIn")
    @ApiOperation("活动签到接口")
    public R checkIn(@Valid @RequestBody CheckInForm form, @RequestHeader("token") String token){
        int userId = jwtUtil.getUserId(token);
        String id = form.getId();
        ArrayList list = new ArrayList();
        list.add(userId);
        HashMap map = new HashMap();
        map.put("userId", userId);
        map.put("id", id);
        map.put("checkedIn", list.toString());
        int row = activityService.checkIn(map);
        int count = activityDao.isCheckIn(id);
        if(count == 0){
            throw new HJException("签到时间不在活动时间内！");
        }
        if (row == 0){
            throw new HJException("签到失败！");
        }
        if (row == -1){
            throw new HJException("你已经签到，请勿重复签到！");
        }
        return R.ok();
    }
}
